home *** CD-ROM | disk | FTP | other *** search
/ Utilities Professional 1-1500 / Utilities Professional 1-1500 (1994)(WPD)[!].iso / 12511500 / var1312.dms / var1312.adf / HP11 / IO.C < prev    next >
C/C++ Source or Header  |  1991-06-11  |  9KB  |  325 lines

  1. #include "exec/types.h"
  2.  
  3. #include "stdlib.h"
  4. #include "stdio.h"
  5. #include <math.h>
  6. #include "string.h"
  7.  
  8. #include "hp11/hp11.h"
  9. #include "hp11/amiga/amiga.h"
  10. #include "hp11/ins.h"
  11. #include "hp11/io.h"
  12. #include "hp11/kbd.h"
  13. #include "hp11/codes.h"
  14. #include "hp11/prog_codes.h"
  15.  
  16. #define MAXRUN 4 /* Length of time running is displayed */
  17.  
  18. #define FOREVER for (;;)
  19.  
  20. int comma;
  21.  
  22. static char *stpich(char *p, int c) /* insert character c at front of string p */
  23. {
  24.    movmem(p, p + 1, strlen(p) + 1);
  25.    *p = c;
  26.  
  27.    return(p);
  28. }
  29.  
  30. int GetKey() /* Read a key & wait for its release */
  31. {
  32.    int key;
  33.  
  34.    key = PollKey(TRUE);
  35.    RelKey();
  36.  
  37.    return(key);
  38. }
  39.  
  40. enum KeyTypes ReadKey(code) /* Read a complete key sequence, & return
  41.  its type, intrsuction or action. */
  42. register WORD *code;
  43. {
  44.    register struct Key *curtkey;
  45.    register int key, offset;
  46.    register BOOL noKey; /* if an invalid sequence is returned, don't read a new key,
  47.       reuse the one which caused the error. This is set to false when that happens */
  48.    register enum KeyTypes ret;
  49.  
  50.    noKey = TRUE; /* no key read */
  51.  
  52.    FOREVER {
  53.       offset = 0; /* f or g not pressed */
  54.  
  55.       FOREVER { /* This loop reads a key from the main, f or g shifted keyboards.
  56.      Further refinements (eg sto) are done algorithmically, to save space */
  57.      if (noKey) key = PollKey(TRUE); /* obtain next key */
  58.      Dispf(FALSE); Dispg(FALSE);
  59.      noKey = TRUE;
  60.      if (key == 31) { /* f pressed, toggle its status */
  61.         offset = (offset == NUMKEYS) ? 0 : (Dispf(TRUE), NUMKEYS);
  62.         RelKey();
  63.      }
  64.      else if (key == 32) { /* g */
  65.         offset = (offset == NUMKEYS + NUMKEYS) ? 0 : (Dispg(TRUE), NUMKEYS + NUMKEYS);
  66.         RelKey();
  67.      }
  68.      else break;/* got a key, exit from loop */
  69.       }
  70.       if (User && key < 5) offset ^= NUMKEYS; /* Toggle f for first five keys. This
  71.        doesn't affect g because the bit patterns are exclusive (42 & 84 = 0) */
  72.  
  73.       Dispf(FALSE); Dispg(FALSE);
  74.  
  75.       curtkey = mainKbd + offset + key; /* find address of (eventually shifted) key */
  76.  
  77.       switch (curtkey->Sort) {
  78.      case Action:
  79.         *code = curtkey->Act;
  80.         return(Action);
  81.      case Instruction:
  82.         *code = curtkey->Code;
  83.         return(Instruction);
  84.      case Prefix: /* Key is a prefix, execute corresponding routine */
  85.         RelKey();
  86.         ret = (*(curtkey->Suffix))(code);
  87.         if (ret != Invalid) return(ret); /* if successful */
  88.  
  89.         key = *code; /* else, invalid keycode returnedin code field for reuse */
  90.         noKey = FALSE; /* a key is already available */
  91.         break;
  92.      case Invalid: /* An inavlid f or g sequence was entered, retry it with
  93.         the f or g prefix stripped. Therefore all obtainable main keyboard sequences
  94.         must exist, otherwise the program enters an infinite loop retrying constantly
  95.         the same nonexistent keycode */
  96.         key %= NUMKEYS;
  97.         noKey = FALSE;
  98.         break;
  99.       }
  100.    }
  101. }
  102.  
  103. /* Return position n on the liquid cristal display in string t */
  104. int scrpos(t, n)
  105. char *t;
  106. register int n;
  107. {
  108.    register char *s = t;
  109.    register int pos;
  110.  
  111.    pos = 0;
  112.    while (pos <= n && *s) { /* go on till end of string or beyond position n on display */
  113.       if (*s != '.' && *s != ',') pos++; /* . & , take no space on the display */
  114.       s++;
  115.    }
  116.    return((int)((s - t) - 1 - (pos - n))); /* pos - n  is there to take care of the overshoot. If
  117.    n is beyond the end of the string, the position returned may well be wildly beyond the
  118.    actual end of the string */
  119. }
  120.  
  121. /* Return the length taken up on the screen by the string */
  122. int scrlen(s)
  123. register char *s;
  124. {
  125.    register int cnt = 0;
  126.  
  127.    while (*s) {
  128.       if (*s != '.' && *s != ',') cnt++; /* . & , take no space on the display */
  129.       s++;
  130.    }
  131.  
  132.    return(cnt);
  133. }
  134.  
  135. /* format string s in hp11 display format (without exponent) so that it takes
  136.  n spaces in the display. s isn't modified */
  137. static char *CvtStd(char *s, int n)
  138. {
  139.    static char buf[20];
  140.    register char *p;
  141.    register int i, nb;
  142.    register int digit_separator = comma ? '.' : ','; /* separator according to current setting */
  143.  
  144.    strcpy(buf, s); /* copy string to safe work buffer */
  145.  
  146.    if ((p = strchr(buf, '.')) == NULL) { /* find position of . */
  147.       p = buf + strlen(buf);
  148.       if (!entering) *p = comma ? ',' : '.';
  149.       *(p + 1) = '\0';
  150.    }
  151.    else if (comma) *p = ','; /* Replace . by , if necessary */
  152.  
  153.    while ((p -= 3) - buf > 1) /* Add , (or .) to string every 3 digits */
  154.       stpich(p, digit_separator);
  155.  
  156.    nb = n - scrlen(buf);
  157.    for (i = 1; i <= nb; i++) strcat(buf, " "); /* pad with spaces to required screen length */
  158.    buf[scrpos(buf, n) + 1] = '\0'; /* cut at n characters */
  159.  
  160.    return(buf);
  161. }
  162.  
  163. /* format string s in hp11 display format (with exponent) */
  164. static char *CvtExpo(char *s, char *e)
  165. {
  166.    if (strlen(e) > 3) { /* deal with roundoff towards 1e100 when nb too big */
  167.       e = " 99"; /* exponent is 99 */
  168.       strncpy(s + 1, "9.999999999", strlen(s + 1)); /* mantissa is enough 9's */
  169.    }
  170.  
  171.    return(strcat(CvtStd(s, 8), e));
  172. }
  173.  
  174. /* convert x to scientific format with n digits. Returns it in a static buffer (from CvtStd) */
  175. static char *Scient(double x, int n)
  176. {
  177.    char buf[20];
  178.    register char *pe;
  179.  
  180.    sprintf(buf, "% .*E", n, x); /* Scientific format with n digits */
  181.    pe = strchr(buf, 'E'); /* split string into mantissa & exponent */
  182.    *pe++ = '\0';
  183.    /* if (*pe == '+') *pe = ' '; A + is displayed as a space by the Display routine anyway */
  184.  
  185.    return(CvtExpo(buf, pe));
  186. }
  187.  
  188. /* Convert x to fix n format */
  189. static char *Fixed(double x, int n)
  190. {
  191.    char buf[80];
  192.  
  193.    sprintf(buf, "% .*f", n, x);
  194.  
  195.    return(CvtStd(buf, 11));
  196. }
  197.  
  198. /* Eng n format */
  199. static char *Engin(double x, int n)
  200. {
  201.    char expbuf[10], buf[80];
  202.    register char *pe;
  203.    double mantissa;
  204.    register int exponent, dif;
  205.  
  206.    sprintf(buf, "%.*E", n, x); /* print enough digits */
  207.    *(pe = strchr(buf, 'E')) = '\0';
  208.    mantissa = atof(buf); /* get mantissa & exponent */
  209.    exponent = atoi(pe + 1);
  210.  
  211.    /* Round exponent down to a multiple of 3 */
  212.    dif = exponent % 3;
  213.    if (dif < 0) dif += 3;
  214.    exponent -= dif; /* calculate new exponent & mantissa */
  215.    mantissa *= pow(10.0, (double)dif);
  216.  
  217.    /* Convert them to string */
  218.    sprintf(buf, "% .*f", (n - dif > 0) ? n - dif : 0, mantissa);
  219.    sprintf(expbuf, "%c%02d", (exponent < 0) ? '-' : ' ', iabs(exponent)); /* pad exponent with 0's, hence %02d not %2d */
  220.  
  221.    return(CvtExpo(buf, expbuf));
  222. }
  223.  
  224. /* Display current trig mode */
  225. static void DispAngle(void)
  226. {
  227.    switch (Angles) {
  228.       case grad:DispG(TRUE);
  229.       case rad:DispRAD(TRUE);
  230.       case deg:break;
  231.    }
  232. }
  233.  
  234. /* Display current x value in normal mode, running in run mode */
  235. void Disp()
  236. {
  237.    static int runcnt = MAXRUN;
  238.    static BOOL runon;
  239.  
  240.    if (running) { /* Flash running on and off every MAXRUN calls */
  241.       if (fast) { /* Display Running only once in fast mode */
  242.      if (!runon) {
  243.         Display("  Running");
  244.         runon = TRUE; /* Running displayed */
  245.      }
  246.       }
  247.       else if (runcnt-- == 0) Display("");
  248.       else if (runcnt <= -MAXRUN) {
  249.      runcnt = MAXRUN;
  250.      Display("  Running");
  251.       }
  252.    }
  253.    else {
  254.       runon = FALSE; /* Running not displayed */
  255.       if (entering) /* Display number entry strings */
  256.      if (expo) Display(CvtExpo(strx, expx)); /* with exponent */
  257.      else Display(CvtStd(strx, 11));
  258.       else
  259.      Display(NbStr(X));
  260.  
  261.       DispAngle();
  262.       if (User) DispUSER(TRUE);
  263.    }
  264. }
  265.  
  266. char *NbStr(x)
  267. double x;
  268. {
  269.    switch (Mode) { /* Display x according to display mode */
  270.       case fix:if ((fabs(X) >= minfix / 2.0 || X == 0.0) && fabs(X) < 1E10) {
  271.           /* Number can be displayed in fix mode */
  272.           return(Fixed(X, Digits));
  273.            }
  274.            /* fall through for call to Scient */
  275.       case sci:return(Scient(X, Digits));
  276.       case eng:return(Engin(X, Digits));
  277.    }
  278. }
  279.  
  280. /* Display Error n, & wait for a key to be pressed */
  281. void Error(n)
  282. int n;
  283. {
  284.    register char *buf;
  285.  
  286.    entering = FALSE; /* end of digit entry */
  287.    error = TRUE; /* an error has occured */
  288.    buf = "  Error  ";
  289.    buf[8] = n; buf[9] ='\0';
  290.  
  291.    if (!running) RelKey();
  292.    Display(buf);
  293.    GetKey();
  294.  
  295. }
  296.  
  297. /* Display current program line */
  298. void DisplayLine()
  299. {
  300.    register int c1 = keycodes[Prog[PC]].c1, c2 = keycodes[Prog[PC]].c2,
  301.         c3 = keycodes[Prog[PC]].c3;
  302.    char _buf[20], _insbuf[20];
  303.    register char *buf = _buf, *insbuf = _insbuf;
  304.    register int point = comma ? ',' : '.'; /* separator according to current setting */
  305.  
  306.    sprintf(buf, " %03d-", PC); /* prepare program line */
  307.  
  308.    /* Prepare instruction buffer */
  309.    if (PC == 0) insbuf[0] = '\0'; /* nothing at line 0 */
  310.    else switch (keycodes[Prog[PC]].Type) { /* there are 6 methods for displaying a line */
  311.       case ONECODE: sprintf(insbuf, "%6d", c1); break; /*     nn eg SIN or 9 */
  312.       case TWOCODE: sprintf(insbuf, "%3d%3d", c1, c2); break; /*  nn nn eg g LOG */
  313.       case TWOCODE_9: sprintf(insbuf, "%4d%2d", c1, c2); break; /*  nn n eg STO 5*/
  314.       case TWOCODE_PT: sprintf(insbuf, "%4d %c%1d", c1, point, c2); break; /* nn .n eg RCL .6 */
  315.       case THREECODE: sprintf(insbuf, "%2d,%2d,%2d", c1, c2, c3); break; /* nn,nn,nn eg f HYP SIN */
  316.       case THREECODE_PT: sprintf(insbuf, "%2d,%2d, %c%1d", c1, c2, point, c3); break; /* nn,nn, .n eg STO + .0 */
  317.    }
  318.  
  319.    Display(strcat(buf, insbuf));
  320.  
  321.    DispAngle();
  322.    if (User) DispUSER(TRUE);
  323. }
  324.  
  325.